package cs.study.test;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;

public class Server {

	public static void main(String[] args) throws Exception {
		//1 第一个线程组 是用于接收Client端连接的
		EventLoopGroup bossGroup = new NioEventLoopGroup();
		//2 第二个线程组 是用于实际的业务处理操作的
		EventLoopGroup workerGroup = new NioEventLoopGroup();
		
		//3 创建一个辅助类Bootstrap，对Server进行一系列的配置
		ServerBootstrap b = new ServerBootstrap(); 
		//3.1把俩个工作线程组加入进来
		b.group(bossGroup, workerGroup)
		//3.2指定使用NioServerSocketChannel这种类型的通道
		 .channel(NioServerSocketChannel.class)
		//3.3一定要使用 childHandler 去绑定具体的 事件处理器
		 .childHandler(new ChannelInitializer<SocketChannel>() {
			@Override
			protected void initChannel(SocketChannel sc) throws Exception {
				sc.pipeline().addLast(new ServerHandler());
			}
		})

		/**
		 * 服务器端的TCP内核模块维护有2个队列，我们称之为A、B
		 * 客户端向服务端connect的时候，会发送带有SYN标志的包（第一次握手）
		 * 服务端送到了来自客户端的SYN后时，向客户端发送SYN ACK确认（第二次握手）
		 * 此时TCP内核模块把客户端连接加入到队列A中，然后服务端收到客户端发来的ACK时（第三次握手）
		 * TCP内核模块吧客户端连接从A队列移动到B队列，连接完成，应用程序accept会返回
		 * 也就是说accept从B队列中取出完成三次握手的连接
		 * A队列和B队列的长度之和就是backlog，当A、B队列长度之和大于backlog时，新连接将会被TCP内核拒绝
		 * 所以，如果backlog过小，可能会出现连接跟不上，A、B队列满了导致新的客户端无法连接
		 * 要注意的是：backlog对程序支持的连接数并无影响，backlog影响的只是还没有被accept取出的连接
		 */
		//设置TCP缓冲区
		//.option(ChannelOption.SO_BACKLOG, 128)
		//保持连接
		.childOption(ChannelOption.SO_KEEPALIVE, true);

		//绑定指定的端口 进行监听
		ChannelFuture f = b.bind(8765).sync(); 


		//Thread.sleep(1000000);
		//阻塞服务端
		f.channel().closeFuture().sync();
		
		bossGroup.shutdownGracefully();
		workerGroup.shutdownGracefully();
		 
		
		
	}
	
}
